import { ChangeDetectorRef, Component, Input, OnInit, ViewChild } from '@angular/core';
import { _HttpClient, MenuService } from '@delon/theme';
import { NzTreeNode } from 'ng-zorro-antd/core/tree/nz-tree-base-node';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { NzDrawerRef } from 'ng-zorro-antd/drawer';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzFormatEmitEvent, NzTreeComponent } from 'ng-zorro-antd/tree';
import { zip } from 'rxjs';
import { finalize } from 'rxjs/operators';

@Component({
  selector: 'app-sys-assign-menu',
  templateUrl: './menu.component.html'
})
export class SysAssignMenuComponent implements OnInit {
  i: any;
  @Input() record: NzSafeAny;
  nodes: any = [];
  checked: any;
  hasChecked = false;
  checkedNodes: number[] = [];
  halfCheckedNodes: number[] = [];

  @ViewChild('treeComponent', { static: false }) treeComponent!: NzTreeComponent;

  constructor(
    public http: _HttpClient,
    private drawer: NzDrawerRef,
    private cdr: ChangeDetectorRef,
    private msgSrv: NzMessageService,
    private menuService: MenuService
  ) {}

  ngOnInit(): void {
    this.loadData();
  }

  loadData(): void {
    if (this.record.ID > 0) {
      zip(this.http.get(`api/menus`), this.http.get(`api/role/${this.record.ID}/menus`))
        .pipe(
          finalize(() => {
            this.cdr.detectChanges();
          })
        )
        .subscribe(([nodes, checked]: [NzSafeAny, NzSafeAny]) => {
          this.i = true;
          this.nodesFormat(nodes.data);
          this.checkFormat(checked.data);
        });
    }
  }

  save(): void {
    const nodes = this.treeComponent.getTreeNodes();
    this.getCheckedNodeIds(nodes);
    this.http
      .post(`api/role/${this.record.ID}/menus`, { checked: this.checkedNodes, halfChecked: this.halfCheckedNodes })
      .subscribe(res => {
        if (res.err_code != 0) {
          this.msgSrv.error(res.msg);
          return;
        }
        this.msgSrv.success(res.msg);
        this.drawer.close(true);
        this.menuService.resume();
      });
  }

  getCheckedNodeIds(nodes: NzTreeNode[]) {
    for (let i = 0; i < nodes.length; i++) {
      let node = nodes[i];
      if (node.origin.id <= 0) {
        continue;
      }
      if (node.isChecked) {
        if (!node.isDisabled && node.isLeaf) {
          this.checkedNodes.push(node.origin.ID);
        } else {
          let hasDisabled = false;
          node.children.forEach((value: NzTreeNode) => {
            if (value.isDisabled) {
              hasDisabled = true;
              return;
            }
          });
          if (hasDisabled) {
            this.halfCheckedNodes.push(node.origin.ID);
          } else {
            this.checkedNodes.push(node.origin.ID);
          }
        }
      } else if (node.isHalfChecked) {
        this.halfCheckedNodes.push(node.origin.ID);
      }
      if (node.children.length) {
        this.getCheckedNodeIds(node.children);
      }
    }
  }

  close(): void {
    this.drawer.close();
  }

  checkFormat(checked: any): void {
    if (checked) {
      this.hasChecked = true;
      this.cdr.detectChanges();
      this.checked = [];
      for (let i = 0; i < checked.length; i++) {
        this.checked.push(checked[i].menu_id);
      }
    }
  }

  nodesFormat(nodes: any): void {
    console.log(nodes);
    for (let i = 0; i < nodes.length; i++) {
      nodes[i].key = nodes[i].ID;
      nodes[i].title = nodes[i].name;
      if (nodes[i].children) {
        this.nodesFormat(nodes[i].children);
      } else {
        nodes[i].isLeaf = true;
      }
    }
    this.nodes = nodes;
    this.cdr.detectChanges();
  }

  checkBoxChangeEvent(event: NzFormatEmitEvent): void {
    console.log(event);
    this.hasChecked = this.treeComponent.getCheckedNodeList().length > 0;
    this.cdr.detectChanges();
  }
}
